package com.efrei.schoolmanager.views;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import java.util.Set;

import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;

import com.efrei.schoolmanager.controlers.ControleurNote;
import com.efrei.schoolmanager.exceptions.LogicException;
import com.efrei.schoolmanager.model.ModeleListeNotes;
import com.efrei.schoolmanager.model.obj.Classe;
import com.efrei.schoolmanager.model.obj.Matiere;
import com.efrei.schoolmanager.views.components.CustomButton;
import com.efrei.schoolmanager.views.components.CustomTextField;

public class VueGestionNotes extends JPanel {
	private static final long serialVersionUID = -5330855022788312069L;

	private final static String TITLE = "Gestion des notes";
	/* Panels */
	private JPanel mainPanel, titlePanel, notesPanel, boutonsPanel,
			criteresPanel;
	/* Labels */
	private JLabel titleLabel, classeLabel, matiereLabel, profEnseignantLabel;
	/* Zones de textes mono-ligne */
	private CustomTextField profEnseignantTextField;

	/* Boutons */
	private CustomButton ajouterNoteButton, enregistrerNotesButton;
	/* Listes déroulantes */
	private JComboBox classesComboBox, matieresComboBox;

	private JTable notesTable;
	private JScrollPane tableau;

	// Controleur qui fera le lien avec le model pour la vue
	private ControleurNote controleur;
	private ModeleListeNotes modeleTableau;
	private final VueGenerale vueParente;

	public VueGestionNotes(final VueGenerale vueParente) throws LogicException {
		super();
		this.vueParente = vueParente;
		new Thread(new Runnable() {
			@Override
			public void run() {
				boolean error = false;
				try {
					//chargement de l'écran
					initGlobal();
				} catch (final Exception e) {
					//en cas d'erreur, on efface tout
					error = true;
					SwingUtilities.invokeLater(new Runnable() {
						@Override
						public void run() {
							vueParente.displayError(e);
							vueParente.removePanel();
							vueParente.stopBarreChargement();
						}
					});
				}
				if(!error)
					SwingUtilities.invokeLater(new Runnable() {
						@Override
						public void run() {
							vueParente.stopBarreChargement();
						}
					});
			}
		}).start();
		vueParente.startBarreChargement();
	}

	private void initGlobal() throws LogicException {
		// Propage les exceptions si Hibernate a un probleme
		this.controleur = new ControleurNote();

		/* Composants */
		initLabels();
		initTextFields();
		initButtons();
		initComboBox();
		initTable();
		remplirTitlePanel();
		remplirBoutonsPanel();
		remplirCriteresPanel();
		remplirNotesPanel();
		remplirMainPanel();

		/* Panel principal */
		initContentPane();

		/* Frame */
		configurerVue();
	}

	private void configurerVue() {
		// Permet redimensionnement de l'écran
		Dimension preferedSize = getPreferredSize();
		Dimension dimensionIdeale = new Dimension(preferedSize.width,
				preferedSize.height + 28);
		setMinimumSize(dimensionIdeale);
		setSize(dimensionIdeale);
		setVisible(true);
	}

	private void initContentPane() {
		setLayout(new BorderLayout());
		add(mainPanel, BorderLayout.CENTER);
		add(titlePanel, BorderLayout.NORTH);
	}

	private void initLabels() {
		titleLabel = new JLabel(TITLE);
		titleLabel.setFont(new Font("Arial", Font.BOLD, 20));
		classeLabel = new JLabel("Classe:");
		matiereLabel = new JLabel("Matiere:");
		matiereLabel.setVisible(false);
		profEnseignantLabel = new JLabel("Professeur enseignant:");
		profEnseignantLabel.setVisible(false);
	}

	private void initTextFields() {
		/* Text fields */
		profEnseignantTextField = new CustomTextField("",
				new Dimension(200, 20));
		profEnseignantTextField.setVisible(false);
		profEnseignantTextField.setEnabled(false);
	}

	private void initButtons() {
		/* Listeners */
		AjouterNoteButtonListener ajouterNoteListener = new AjouterNoteButtonListener();
		EnregistrerNotesButtonListener enregistrerNotesListener = new EnregistrerNotesButtonListener();
		ajouterNoteButton = new CustomButton("Nouvelle note");
		ajouterNoteButton.addActionListener(ajouterNoteListener);
		enregistrerNotesButton = new CustomButton("Enregistrer notes");
		enregistrerNotesButton.addActionListener(enregistrerNotesListener);
	}

	private void initComboBox() {
		/* Listeners */
		ClassesComboBoxListener classesListener = new ClassesComboBoxListener();
		MatieresComboBoxListener matieresListener = new MatieresComboBoxListener();
		/* Combobox */
		// Liste de pays
		classesComboBox = new JComboBox();
		classesComboBox.addItem("--Liste des classes--");
		try {
			List<Classe> classes = controleur.getClasses();
			for (Classe classe : classes) {
				classesComboBox.addItem(classe);
			}
		} catch (Exception e) {
			e.printStackTrace();
			System.err.println("Echec de la recupération des classes");
		}
		classesComboBox.addActionListener(classesListener);

		matieresComboBox = new JComboBox();
		matieresComboBox.addActionListener(matieresListener);
		matieresComboBox.setVisible(false);
	}

	private void initTable() {
		modeleTableau = new ModeleListeNotes(controleur);
		notesTable = new JTable(modeleTableau);
		notesTable.setPreferredScrollableViewportSize(new Dimension(675, 400));
		tableau = new JScrollPane(notesTable,
				JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
				JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
		notesTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
	}

	private void remplirTitlePanel() {
		titlePanel = new JPanel();
		titlePanel.add(titleLabel);
	}

	private void remplirBoutonsPanel() {
		boutonsPanel = new JPanel();
		boutonsPanel.add(ajouterNoteButton);
		boutonsPanel.add(enregistrerNotesButton);
	}

	private void remplirCriteresPanel() {
		criteresPanel = new JPanel();
		GroupLayout gl = new GroupLayout(criteresPanel);
		criteresPanel.setLayout(gl);
		// Espacement des composants
		gl.setAutoCreateGaps(true);
		// Espacement entre composants et conteneur
		gl.setAutoCreateContainerGaps(true);

		// Groupe sequentiel sur l'axe horizontal
		GroupLayout.SequentialGroup hGroup = gl.createSequentialGroup();

		// Constitution des groupes paralleles horizontalement
		/* 1e colonne */
		hGroup.addGroup(gl.createParallelGroup().addComponent(classeLabel));
		/* 2e colonne */
		hGroup.addGroup(gl.createParallelGroup().addComponent(classesComboBox));
		/* 3e colonne */
		hGroup.addGroup(gl.createParallelGroup().addComponent(matiereLabel));
		/* 4e colonne */
		hGroup.addGroup(gl.createParallelGroup().addComponent(matieresComboBox));
		/* 5e colonne */
		hGroup.addGroup(gl.createParallelGroup().addComponent(
				profEnseignantLabel));
		/* 6e colonne */
		hGroup.addGroup(gl.createParallelGroup().addComponent(
				profEnseignantTextField));
		gl.setHorizontalGroup(hGroup);

		// Groupe sequentiel sur l'axe vertical
		GroupLayout.SequentialGroup vGroup = gl.createSequentialGroup();

		// Constitution des groupes paralleles verticalement
		/* 1e ligne */
		vGroup.addGroup(gl.createParallelGroup(Alignment.BASELINE)
				.addComponent(classeLabel).addComponent(classesComboBox)
				.addComponent(matiereLabel).addComponent(matieresComboBox)
				.addComponent(profEnseignantLabel)
				.addComponent(profEnseignantTextField));
		gl.setVerticalGroup(vGroup);
	}

	private void remplirNotesPanel() {
		notesPanel = new JPanel();
		notesPanel.add(tableau);
	}

	private void remplirMainPanel() {
		mainPanel = new JPanel();
		GroupLayout gl = new GroupLayout(mainPanel);
		mainPanel.setLayout(gl);
		// Espacement des composants
		gl.setAutoCreateGaps(true);
		// Espacement entre composants et conteneur
		gl.setAutoCreateContainerGaps(true);

		// Groupe sequentiel sur l'axe horizontal
		GroupLayout.SequentialGroup hGroup = gl.createSequentialGroup();

		// Constitution des groupes paralleles horizontalement
		/* 1e colonne */
		hGroup.addGroup(gl.createParallelGroup().addComponent(criteresPanel)
				.addComponent(notesPanel).addComponent(boutonsPanel));
		gl.setHorizontalGroup(hGroup);

		// Groupe sequentiel sur l'axe vertical
		GroupLayout.SequentialGroup vGroup = gl.createSequentialGroup();

		// Constitution des groupes paralleles verticalement
		/* 1e ligne */
		vGroup.addGroup(gl.createParallelGroup(Alignment.BASELINE)
				.addComponent(criteresPanel));
		/* 2e ligne */
		vGroup.addGroup(gl.createParallelGroup(Alignment.BASELINE)
				.addComponent(notesPanel));
		/* 3e ligne */
		vGroup.addGroup(gl.createParallelGroup(Alignment.BASELINE)
				.addComponent(boutonsPanel));
		gl.setVerticalGroup(vGroup);
	}

	public static String getTitle() {
		return TITLE;
	}

	/* Listeners */
	class AjouterNoteButtonListener implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent e) {
			modeleTableau.newControle();
		}

	}

	class EnregistrerNotesButtonListener implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent e) {
			// Valider et on quitte
			new Thread(new ControlerValidator(controleur, vueParente)).start();
			// Pendant ce temps, lancer un chargement
			vueParente.startBarreChargement();
		}
	}

	class ClassesComboBoxListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			JComboBox cb = (JComboBox) e.getSource();
			int index = cb.getSelectedIndex();
			if (index != 0) {
				if (cb.getSelectedItem() != controleur.getClasseCourante()) {
					final Classe classechoisie = (Classe) cb.getSelectedItem();
					new Thread(new Runnable() {
						@Override
						public void run() {
							//on recupere les matieres en base
							controleur.getMatieres(classechoisie);
							SwingUtilities.invokeLater(new Runnable() {
								@Override
								public void run() {
									vueParente.stopBarreChargement();
								}
							});
						}
					}).start();
					vueParente.startBarreChargement();
					
					matieresComboBox.removeAllItems();
					matieresComboBox.addItem("--Liste des matieres--");
					// Afficher les matieres pour la classe courante
					Set<Matiere> matieres = controleur.getMatieres((Classe) cb
							.getSelectedItem());
					controleur.setMatiereCourante(null);
					for (Matiere matiere : matieres) {
						matieresComboBox.addItem(matiere);
					}
					matiereLabelStatus(true);
				}
			} else {
				controleur.setMatiereCourante(null);
				controleur.setClasseCourante(null);
				matiereLabelStatus(false);
			}
			// Notifier le modele
			modeleTableau.refresh();
			// Par defaut la combobox est designe le premier element
			matieresComboBox.setSelectedIndex(0);
		}

		private void matiereLabelStatus(boolean enable) {
			matiereLabel.setVisible(enable);
			matieresComboBox.setVisible(enable);
		}
	}

	class MatieresComboBoxListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			JComboBox cb = (JComboBox) e.getSource();
			int index = cb.getSelectedIndex();
			if (index != 0 && controleur.getClasseCourante() != null) {
				Matiere matiereSelectionne = (Matiere) cb.getSelectedItem();
				// Matiere voulue
				controleur.setMatiereCourante(matiereSelectionne);
				// Affichage de l'enseignant responsable
				if (controleur.getClasseCourante().getEnseignantsResponsables()
						.containsKey(matiereSelectionne))
					refreshResponsableLabel(true,
							"Responsable: "+ controleur.getClasseCourante()
											.getEnseignantsResponsables()
											.get(matiereSelectionne));
				else
					System.err.println("Pas d'enseignant responsable pour matiere "+matiereSelectionne);

			} else {
				// Desactivation du tableau
				controleur.setMatiereCourante(null);
				refreshResponsableLabel(false, "");
			}
			// Notifier le modele
			modeleTableau.refresh();
		}

		private void refreshResponsableLabel(boolean enable, String text) {
			profEnseignantTextField.setText(text);
			profEnseignantLabel.setVisible(enable);
			profEnseignantTextField.setVisible(enable);
		}
	}
}
